package com.fanshilz.flower2025.apps.wechatminiapp.wechatUser.controller;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.PhoneUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.servlet.JakartaServletUtil;
import com.fanshilz.flower2025.apps.admin.aliyun.req.AttachmentUploadReq;
import com.fanshilz.flower2025.apps.wechatminiapp.satoken.StpWechatUtil;
import com.fanshilz.flower2025.apps.wechatminiapp.satoken.WechatCurrentUser;
import com.fanshilz.flower2025.apps.wechatminiapp.wechatUser.req.*;
import com.fanshilz.flower2025.apps.wechatminiapp.wechatUser.resp.*;
import com.fanshilz.flower2025.business.flower.attachment.entity.Attachment;
import com.fanshilz.flower2025.business.flower.attachment.service.IAttachmentService;
import com.fanshilz.flower2025.business.flower.projectLink.entity.ProjectLinkStatusEnum;
import com.fanshilz.flower2025.business.flower.projectLink.service.IProjectLinkService;
import com.fanshilz.flower2025.business.flower.projectMsg.entity.Msg;
import com.fanshilz.flower2025.business.flower.projectMsg.entity.MsgStatusEnum;
import com.fanshilz.flower2025.business.flower.projectMsg.service.IMsgService;
import com.fanshilz.flower2025.business.flower.sms.entity.Sms;
import com.fanshilz.flower2025.business.flower.sms.service.ISmsService;
import com.fanshilz.flower2025.business.flower.userIdentity.entity.UserIdentity;
import com.fanshilz.flower2025.business.flower.userIdentity.entity.UserIdentityStatusEnum;
import com.fanshilz.flower2025.business.flower.userIdentity.service.IUserIdentityService;
import com.fanshilz.flower2025.business.flower.wechatUser.entity.WechatUser;
import com.fanshilz.flower2025.business.flower.wechatUser.service.IWechatUserService;
import com.fanshilz.flower2025.framework.aliyun.sms.AliyunSmsUtil;
import com.fanshilz.flower2025.framework.exception.CodeException;
import com.fanshilz.flower2025.framework.resp.Resp;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import io.github.linpeilie.Converter;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.Valid;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Date;
import java.util.List;

import static com.fanshilz.flower2025.business.flower.projectLink.entity.table.ProjectLinkTableDef.PROJECT_LINK;
import static com.fanshilz.flower2025.business.flower.projectMsg.entity.table.MsgTableDef.MSG;
import static com.fanshilz.flower2025.business.flower.sms.entity.table.SmsTableDef.SMS;
import static com.fanshilz.flower2025.business.flower.userIdentity.entity.table.UserIdentityTableDef.USER_IDENTITY;
import static com.fanshilz.flower2025.business.flower.wechatUser.entity.table.WechatUserTableDef.WECHAT_USER;

@Tag(name = "微信用户")
@Slf4j
@RestController
@RequestMapping("/wechat/user")
public class WechatUserController {

    @Resource
    private IWechatUserService wechatUserService;
    @Resource
    private ISmsService smsService;
    @Resource
    private WxMaService wxMaService;
    @Resource
    private IMsgService msgService;
    @Resource
    private Converter converter;
    @Resource
    private IAttachmentService attachmentService;
    @Resource
    private IUserIdentityService userIdentityService;
    @Resource
    private IProjectLinkService projectLinkService;

    @Operation(summary = "切换身份认证")
    @PostMapping("/switchUserIdentity")
    @Transactional
    public Resp<Void> switchUserIdentity(@RequestBody @Valid SwitchUserIdentityReq req) {
        WechatCurrentUser currentUser = StpWechatUtil.currentUser();
        userIdentityService.update(UserIdentity.builder()
                .identitySwitch(false)
                .build(), QueryWrapper.create()
                .where(USER_IDENTITY.CREATE_USER_ID.eq(currentUser.getUserId()))
                .where(USER_IDENTITY.IDENTITY_STATUS_VALUE.eq(UserIdentityStatusEnum.PASS.getValue()))
                .where(USER_IDENTITY.IDENTITY_SWITCH.eq(true)));

        userIdentityService.updateById(UserIdentity.builder()
                .identityId(req.getIdentityId())
                .identitySwitch(true)
                .build());

        UserIdentity ui = userIdentityService.getById(req.getIdentityId());
        currentUser.setIdentityRealName(ui.getIdentityRealName());
        currentUser.setIdentityTypeLabel(ui.getIdentityTypeLabel());
        currentUser.setIdentityTypeValue(ui.getIdentityTypeValue());
        currentUser.setIdentityCompanyName(ui.getIdentityCompanyName());
        StpWechatUtil.refreshCurrentUser(currentUser);

        return Resp.success();
    }

    @Operation(summary = "选择身份认证")
    @PostMapping("/selectUserIdentity")
    public Resp<List<SelectUserIdentityResp>> selectUserIdentity() {
        WechatCurrentUser currentUser = StpWechatUtil.currentUser();
        List<SelectUserIdentityResp> selectUserIdentityResps = userIdentityService.listAs(QueryWrapper.create()
                .where(USER_IDENTITY.CREATE_USER_ID.eq(currentUser.getUserId()))
//                .where(USER_IDENTITY.IDENTITY_SWITCH.eq(false))
                .where(USER_IDENTITY.IDENTITY_STATUS_VALUE.in(UserIdentityStatusEnum.PASS.getValue(), UserIdentityStatusEnum.WAIT_CHECK.getValue())), SelectUserIdentityResp.class);
        return Resp.success(selectUserIdentityResps);
    }

    @Operation(summary = "身份认证上传")
    @PostMapping("/uploadUserIdentity")
    public Resp<UploadUserIdentityResp> uploadUserIdentity(@RequestBody @Valid UploadUserIdentityReq req) {
        UserIdentity ui = converter.convert(req, UserIdentity.class);
        ui.setIdentitySwitch(false);
        ui.setIdentityStatusValue(UserIdentityStatusEnum.WAIT_CHECK.getValue());
        ui.setIdentityStatusLabel(UserIdentityStatusEnum.WAIT_CHECK.getLable());
        userIdentityService.save(ui);
        return Resp.success(new UploadUserIdentityResp(ui.getIdentityId()));
    }

    @Operation(summary = "更新头像已直传alioss")
    @PostMapping("/updateUserHeadImageByAttachment")
    public Resp<Void> updateUserHeadImageByAttachment(@RequestBody @Valid AttachmentUploadReq req) {
        Attachment atta = converter.convert(req, Attachment.class);
        WechatCurrentUser currentUser = StpWechatUtil.currentUser();
        atta.setObjId(currentUser.getUserId());
        attachmentService.save(atta);
        wechatUserService.updateById(WechatUser.builder()
                .userId(currentUser.getUserId())
                .userHeadImgUrl(atta.getFilePath())
                .build());
        currentUser.setUserHeadImgUrl(atta.getFilePath());
        StpWechatUtil.refreshCurrentUser(currentUser);
        return Resp.success();
    }

    @Operation(summary = "更新昵称")
    @PostMapping("/updateUserNickName")
    public Resp<Void> updateUserNickName(@RequestBody @Valid UpdateUserNickNameReq req) {
        WechatCurrentUser currentUser = StpWechatUtil.currentUser();
        wechatUserService.updateById(WechatUser.builder()
                .userId(currentUser.getUserId())
                .userNickName(req.getUserNickName())
                .build());
        currentUser.setUserNickName(req.getUserNickName());
        StpWechatUtil.refreshCurrentUser(currentUser);
        return Resp.success();
    }

    @Operation(summary = "阅读消息")
    @PostMapping("/msgRead")
    public Resp<Void> msgRead(@RequestBody @Valid MsgReadReq req) {
        boolean b = msgService.updateById(Msg.builder()
                .msgId(req.getMsgId())
                .msgStatus(MsgStatusEnum.read)
                .build());
        Assert.isTrue(b, CodeException::new);
        return Resp.success();
    }

    @Operation(summary = "消息列表")
    @PostMapping("/msgList")
    public Resp<List<MsgListResp>> msgList(@RequestBody @Valid MsgListReq req) {
        QueryWrapper qw = QueryWrapper.create();
        qw.orderBy(MSG.MSG_ID.desc());
        Page<MsgListResp> page = msgService.pageAs(Page.of(req.getCurrent(), req.getSize()), qw, MsgListResp.class);
        return Resp.success(page.getRecords());
    }

    @Operation(summary = "个人中心数据")
    @PostMapping("/iCenter")
    public Resp<WechatICenterResp> iCenter() {
        WechatCurrentUser currentUser = StpWechatUtil.currentUser();
        long count = msgService.count(QueryWrapper.create()
                .where(MSG.MSG_STATUS.eq(MsgStatusEnum.send))
                .where(MSG.MSG_USER_ID.eq(currentUser.getUserId())));

        long linkCount = projectLinkService.count(QueryWrapper.create()
                .where(PROJECT_LINK.LINK_TO_USER_ID.eq(currentUser.getUserId()))
                .where(PROJECT_LINK.LINK_STATUS_VALUE.eq(ProjectLinkStatusEnum.WAIT_CHECK.getValue())));

        return Resp.success(new WechatICenterResp(count, linkCount));
    }

    @Operation(summary = "手机号登录")
    @PostMapping("/loginMobile")
    public Resp<Void> loginMobile(@RequestBody @Valid LoginMobileReq req) {
        //  checkCode
        Sms sms = smsService.getOne(QueryWrapper.create()
                .where(SMS.VERIFICATION_CODE.eq(req.getCode()))
                .where(SMS.MOBILE.eq(req.getMobile()))
                .where(SMS.CREATE_TIME.ge(DateUtil.offsetHour(new Date(), -1))));

        Assert.notNull(sms, () -> new CodeException("验证码错误"));

        boolean b = smsService.updateById(Sms.builder()
                .smsId(sms.getSmsId())
                .verificationCodeStatus(1)
                .build());
        Assert.isTrue(b, CodeException::new);

        //
        long count = wechatUserService.count(WECHAT_USER.USER_MOBILE.eq(req.getMobile()));
        if (count > 0) {
            return Resp.error("手机号已经绑定其他微信用户");
        }

        WechatCurrentUser currentUser = StpWechatUtil.currentUser();
        WechatUser wu = WechatUser.builder()
                .userId(currentUser.getUserId())
                .userMobile(req.getMobile())
                .build();
        boolean update = wechatUserService.updateById(wu);
        Assert.isTrue(update, CodeException::new);

        currentUser.setUserNickName(PhoneUtil.hideBetween(req.getMobile()).toString());
        StpWechatUtil.refreshCurrentUser(currentUser);

        return Resp.success();
    }

    @Operation(summary = "发送验证码")
    @PostMapping("/sendCode")
    public Resp<Void> sendCode(@RequestBody @Valid SendCodeReq req) {
        String code = RandomUtil.randomNumbers(6);

        // 是否超出限制 一个小时5条
        long count = smsService.count(QueryWrapper.create()
                .where(SMS.TEMPLATE_CODE.eq("SMS_305067096"))
                .where(SMS.MOBILE.eq(req.getMobile()))
                .where(SMS.CREATE_TIME.ge(DateUtil.offsetHour(new Date(), -1))));
        if (count >= 5) {
            return Resp.error("发送过于频繁");
        }

        // 保存
        boolean save = smsService.save(Sms.builder()
                .templateCode("SMS_305067096")
                .verificationCode(code)
                .verificationCodeStatus(0)
                .mobile(req.getMobile())
                .build());
        Assert.isTrue(save, CodeException::new);

        // 发送验证码
        AliyunSmsUtil.sendVerificationCode(code, req.getMobile());

        return Resp.success();
    }

    @Operation(summary = "获取微信手机号")
    @PostMapping("/fastMobile")
    public synchronized Resp<Void> fastMobile(@RequestBody @Valid FastMobileReq req) {
        WxMaPhoneNumberInfo phoneNumber;
        try {
            phoneNumber = wxMaService.getUserService().getPhoneNumber(req.getCode());
        } catch (WxErrorException e) {
            return Resp.error(e.getMessage());
        }
        log.info("fastMobile phoneNumber : {}", phoneNumber);

        long count = wechatUserService.count(WECHAT_USER.USER_MOBILE.eq(phoneNumber.getPhoneNumber()));
        if (count > 0) {
            return Resp.error("手机号已经绑定其他微信用户");
        }

        WechatCurrentUser currentUser = StpWechatUtil.currentUser();
        WechatUser wu = WechatUser.builder()
                .userId(currentUser.getUserId())
                .userMobile(phoneNumber.getPhoneNumber())
                .build();
        boolean update = wechatUserService.updateById(wu);
        Assert.isTrue(update, CodeException::new);

        currentUser.setUserMobile(PhoneUtil.hideBetween(phoneNumber.getPhoneNumber()).toString());
        StpWechatUtil.refreshCurrentUser(currentUser);

        return Resp.success();
    }

    @Operation(summary = "匿名登录")
    @PostMapping("/login")
    public Resp<Void> login(@RequestBody @Valid JsCodeLoginReq req, HttpServletRequest request) {
        String clientIP = JakartaServletUtil.getClientIP(request);
        log.info("login clientIP : {}", clientIP);
        return wechatUserService.login(req);
    }

    @Operation(summary = "当前用户信息")
    @PostMapping("/current")
    public Resp<WechatCurrentUserResp> current() {
        WechatCurrentUser currentUser = StpWechatUtil.currentUser();
        String userMobile = currentUser.getUserMobile();
        if (StrUtil.isNotBlank(userMobile)) {
            userMobile = PhoneUtil.hideBetween(userMobile).toString();
        }
        WechatCurrentUserResp resp = new WechatCurrentUserResp(
                currentUser.getUserNickName(),
                userMobile,
                currentUser.getUserHeadImgUrl(),
                currentUser.getUserCheckStatus(),
                currentUser.getIdentityRealName(),
                currentUser.getIdentityTypeValue(),
                currentUser.getIdentityTypeLabel(),
                currentUser.getIdentityCompanyName()
        );
        return Resp.success(resp);
    }

    @Operation(summary = "注销 - 退出登录")
    @PostMapping("/logout")
    public Resp<Void> logout() {
        return Resp.success();
    }

}
